#ifndef BITOPS_H
#define BITOPS_H

#include "stm32f4xx.h"

#define ADDR_VALUE(addr) *((volatile u32 *)addr)

#define PERI_BIT_BANK_REGION_BASE 0x40000000
#define PERI_BIT_BANK_ALIAS_BASE 0x42000000

#define PERI_BIT_WORD_ADDR(addr, bit) (PERI_BIT_BANK_ALIAS_BASE + \
    (addr - PERI_BIT_BANK_REGION_BASE) * 32 + bit * 4)
#define REG_ADDR(reg) ((u32)((u32 *)(&(reg))))
#define PERI_BIT_WORD_ADDR_VALUE(reg, bit) \
    (ADDR_VALUE(PERI_BIT_WORD_ADDR(REG_ADDR(reg), bit)))

#define PAI(bit) PERI_BIT_WORD_ADDR_VALUE(GPIOA->IDR, bit)
#define PAO(bit) PERI_BIT_WORD_ADDR_VALUE(GPIOA->ODR, bit)
#define PBI(bit) PERI_BIT_WORD_ADDR_VALUE(GPIOB->IDR, bit)
#define PBO(bit) PERI_BIT_WORD_ADDR_VALUE(GPIOB->ODR, bit)
#define PCI(bit) PERI_BIT_WORD_ADDR_VALUE(GPIOC->IDR, bit)
#define PCO(bit) PERI_BIT_WORD_ADDR_VALUE(GPIOC->ODR, bit)
#define PDI(bit) PERI_BIT_WORD_ADDR_VALUE(GPIOD->IDR, bit)
#define PDO(bit) PERI_BIT_WORD_ADDR_VALUE(GPIOD->ODR, bit)
#define PFI(bit) PERI_BIT_WORD_ADDR_VALUE(GPIOF->IDR, bit)
#define PFO(bit) PERI_BIT_WORD_ADDR_VALUE(GPIOF->ODR, bit)

#endif // BITOPS_H
